<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>关于代码评审那些不得不说的事儿 | 聚名前端团队文档库</title>
    <meta name="generator" content="VuePress 1.9.5">
    <link rel="icon" href="/jm-team/img/juming_ico.ico">
    <script async="async" src="/jm-team/js/jquery/3.6.0/jquery.min.js"></script>
    <meta name="description" content="聚名前端团队文档库">
    <meta name="keywords" content="聚名前端组组件文档库">
    <meta name="theme-color" content="#11a8cd">
    
    <link rel="preload" href="/jm-team/assets/css/0.styles.e434bceb.css" as="style"><link rel="preload" href="/jm-team/assets/js/app.99b82987.js" as="script"><link rel="preload" href="/jm-team/assets/js/5.d18fc731.js" as="script"><link rel="preload" href="/jm-team/assets/js/6.c8a66f32.js" as="script"><link rel="preload" href="/jm-team/assets/js/15.811e7806.js" as="script"><link rel="prefetch" href="/jm-team/assets/js/1.c6f2da47.js"><link rel="prefetch" href="/jm-team/assets/js/10.59953132.js"><link rel="prefetch" href="/jm-team/assets/js/11.53202447.js"><link rel="prefetch" href="/jm-team/assets/js/12.0bebd69a.js"><link rel="prefetch" href="/jm-team/assets/js/13.ab89afda.js"><link rel="prefetch" href="/jm-team/assets/js/14.cccab28e.js"><link rel="prefetch" href="/jm-team/assets/js/16.6b52d65e.js"><link rel="prefetch" href="/jm-team/assets/js/17.2377e7a7.js"><link rel="prefetch" href="/jm-team/assets/js/18.d89e6362.js"><link rel="prefetch" href="/jm-team/assets/js/19.6c8587dd.js"><link rel="prefetch" href="/jm-team/assets/js/2.6f1b5ef5.js"><link rel="prefetch" href="/jm-team/assets/js/20.db588f67.js"><link rel="prefetch" href="/jm-team/assets/js/21.1b6e996b.js"><link rel="prefetch" href="/jm-team/assets/js/22.1efe92bd.js"><link rel="prefetch" href="/jm-team/assets/js/23.27553905.js"><link rel="prefetch" href="/jm-team/assets/js/24.abe75bd5.js"><link rel="prefetch" href="/jm-team/assets/js/25.eedbcfd9.js"><link rel="prefetch" href="/jm-team/assets/js/26.5b1c316e.js"><link rel="prefetch" href="/jm-team/assets/js/27.6d080c8b.js"><link rel="prefetch" href="/jm-team/assets/js/28.4feaaa58.js"><link rel="prefetch" href="/jm-team/assets/js/29.40e0e2d7.js"><link rel="prefetch" href="/jm-team/assets/js/3.92f57443.js"><link rel="prefetch" href="/jm-team/assets/js/30.023098e2.js"><link rel="prefetch" href="/jm-team/assets/js/31.eb0f506d.js"><link rel="prefetch" href="/jm-team/assets/js/32.08513b68.js"><link rel="prefetch" href="/jm-team/assets/js/33.5fb4a125.js"><link rel="prefetch" href="/jm-team/assets/js/34.04ef0c95.js"><link rel="prefetch" href="/jm-team/assets/js/35.ea51e023.js"><link rel="prefetch" href="/jm-team/assets/js/36.41024a3e.js"><link rel="prefetch" href="/jm-team/assets/js/37.c0a8f76a.js"><link rel="prefetch" href="/jm-team/assets/js/38.34a05ead.js"><link rel="prefetch" href="/jm-team/assets/js/39.29d96e24.js"><link rel="prefetch" href="/jm-team/assets/js/40.5b5ed37f.js"><link rel="prefetch" href="/jm-team/assets/js/41.604c91f9.js"><link rel="prefetch" href="/jm-team/assets/js/42.503a5631.js"><link rel="prefetch" href="/jm-team/assets/js/43.f3b4871c.js"><link rel="prefetch" href="/jm-team/assets/js/44.0b07266d.js"><link rel="prefetch" href="/jm-team/assets/js/7.035493f1.js"><link rel="prefetch" href="/jm-team/assets/js/8.d629a04b.js"><link rel="prefetch" href="/jm-team/assets/js/9.214ade66.js">
    <link rel="stylesheet" href="/jm-team/assets/css/0.styles.e434bceb.css">
  </head>
  <body class="theme-mode-light">
    <div id="app" data-server-rendered="true"><div class="theme-container sidebar-open have-rightmenu"><header class="navbar blur"><div title="目录" class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/jm-team/" class="home-link router-link-active"><img src="/jm-team/img/logo.png" alt="聚名前端团队文档库" class="logo"></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/jm-team/" class="nav-link">首页</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="代码规范" class="dropdown-title"><a href="/jm-team/rule/" class="link-title">代码规范</a> <span class="title" style="display:none;">代码规范</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/jm-team/pages/605eb7/" class="nav-link">常规规范</a></li><li class="dropdown-item"><!----> <a href="/jm-team/pages/c126a2/" class="nav-link">移动端规范</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="组件库" class="dropdown-title"><a href="/jm-team/components/" class="link-title">组件库</a> <span class="title" style="display:none;">组件库</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/jm-team/pages/5e4254/" class="nav-link">传统项目文档</a></li><li class="dropdown-item"><!----> <a href="/jm-team/pages/b295e0/" class="nav-link">Vue项目文档</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="工具库" class="dropdown-title"><a href="/jm-team/util/" class="link-title">工具库</a> <span class="title" style="display:none;">工具库</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/jm-team/pages/06fcb4/" class="nav-link">常用的JS代码</a></li><li class="dropdown-item"><!----> <a href="/jm-team/pages/edd363/" class="nav-link">常用的CSS</a></li><li class="dropdown-item"><!----> <a href="/jm-team/pages/80d4db/" class="nav-link">框架类</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="资源库" class="dropdown-title"><a href="/jm-team/assets/" class="link-title">资源库</a> <span class="title" style="display:none;">资源库</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/jm-team/pages/c9bdd7/" class="nav-link">文档资源</a></li></ul></div></div><div class="nav-item"><a href="/jm-team/newspaper/" class="nav-link">前端小报</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="索引" class="dropdown-title"><a href="/jm-team/archives/" class="link-title">索引</a> <span class="title" style="display:none;">索引</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/jm-team/categories/" class="nav-link">分类</a></li><li class="dropdown-item"><!----> <a href="/jm-team/tags/" class="nav-link">标签</a></li><li class="dropdown-item"><!----> <a href="/jm-team/archives/" class="nav-link">归档</a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <div class="sidebar-hover-trigger"></div> <aside class="sidebar" style="display:none;"><!----> <nav class="nav-links"><div class="nav-item"><a href="/jm-team/" class="nav-link">首页</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="代码规范" class="dropdown-title"><a href="/jm-team/rule/" class="link-title">代码规范</a> <span class="title" style="display:none;">代码规范</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/jm-team/pages/605eb7/" class="nav-link">常规规范</a></li><li class="dropdown-item"><!----> <a href="/jm-team/pages/c126a2/" class="nav-link">移动端规范</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="组件库" class="dropdown-title"><a href="/jm-team/components/" class="link-title">组件库</a> <span class="title" style="display:none;">组件库</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/jm-team/pages/5e4254/" class="nav-link">传统项目文档</a></li><li class="dropdown-item"><!----> <a href="/jm-team/pages/b295e0/" class="nav-link">Vue项目文档</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="工具库" class="dropdown-title"><a href="/jm-team/util/" class="link-title">工具库</a> <span class="title" style="display:none;">工具库</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/jm-team/pages/06fcb4/" class="nav-link">常用的JS代码</a></li><li class="dropdown-item"><!----> <a href="/jm-team/pages/edd363/" class="nav-link">常用的CSS</a></li><li class="dropdown-item"><!----> <a href="/jm-team/pages/80d4db/" class="nav-link">框架类</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="资源库" class="dropdown-title"><a href="/jm-team/assets/" class="link-title">资源库</a> <span class="title" style="display:none;">资源库</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/jm-team/pages/c9bdd7/" class="nav-link">文档资源</a></li></ul></div></div><div class="nav-item"><a href="/jm-team/newspaper/" class="nav-link">前端小报</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="索引" class="dropdown-title"><a href="/jm-team/archives/" class="link-title">索引</a> <span class="title" style="display:none;">索引</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/jm-team/categories/" class="nav-link">分类</a></li><li class="dropdown-item"><!----> <a href="/jm-team/tags/" class="nav-link">标签</a></li><li class="dropdown-item"><!----> <a href="/jm-team/archives/" class="nav-link">归档</a></li></ul></div></div> <!----></nav>  <ul class="sidebar-links"><li><a href="/jm-team/pages/85a3b2/" aria-current="page" class="active sidebar-link">关于代码评审那些不得不说的事儿</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level2"><a href="/jm-team/pages/85a3b2/#什么是codereview" class="sidebar-link">什么是CodeReview</a></li><li class="sidebar-sub-header level2"><a href="/jm-team/pages/85a3b2/#为什么要做codereview" class="sidebar-link">为什么要做CodeReview？</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#提升代码质量" class="sidebar-link">提升代码质量</a></li><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#提前发现问题" class="sidebar-link">提前发现问题</a></li><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#经验和知识的传递" class="sidebar-link">经验和知识的传递</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/jm-team/pages/85a3b2/#如何做好codereview" class="sidebar-link">如何做好CodeReview</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#codereview的步骤" class="sidebar-link">CodeReview的步骤</a></li><li class="sidebar-sub-header level4"><a href="/jm-team/pages/85a3b2/#了解改动的背景" class="sidebar-link">了解改动的背景</a></li><li class="sidebar-sub-header level4"><a href="/jm-team/pages/85a3b2/#纵观全局" class="sidebar-link">纵观全局</a></li><li class="sidebar-sub-header level4"><a href="/jm-team/pages/85a3b2/#逐层细化" class="sidebar-link">逐层细化</a></li><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#codereview的关注点" class="sidebar-link">CodeReview的关注点</a></li><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#注意事项" class="sidebar-link">注意事项</a></li><li class="sidebar-sub-header level4"><a href="/jm-team/pages/85a3b2/#codereview的礼节" class="sidebar-link">CodeReview的礼节</a></li><li class="sidebar-sub-header level4"><a href="/jm-team/pages/85a3b2/#codereview应当及时" class="sidebar-link">CodeReview应当及时</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/jm-team/pages/85a3b2/#如何写出对codereview友好的代码" class="sidebar-link">如何写出对CodeReview友好的代码</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#提交前先做好自审" class="sidebar-link">提交前先做好自审</a></li><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#写清楚变更描述" class="sidebar-link">写清楚变更描述</a></li><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#单个变更尽可能短" class="sidebar-link">单个变更尽可能短</a></li><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#注意事项-2" class="sidebar-link">注意事项</a></li><li class="sidebar-sub-header level4"><a href="/jm-team/pages/85a3b2/#注意自己的情绪" class="sidebar-link">注意自己的情绪</a></li><li class="sidebar-sub-header level4"><a href="/jm-team/pages/85a3b2/#codereview流程应该尽早提交" class="sidebar-link">CodeReview流程应该尽早提交</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/jm-team/pages/85a3b2/#关于codereview的几个误区" class="sidebar-link">关于CodeReview的几个误区</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#codereview是纯浪费时间" class="sidebar-link">CodeReview是纯浪费时间？</a></li><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#工期很紧-没时间做codereview" class="sidebar-link">工期很紧，没时间做CodeReview！</a></li><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#只有高级工程师才有资格review别人代码" class="sidebar-link">只有高级工程师才有资格Review别人代码？</a></li><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#都有测试流程了-为什么还要做codereview" class="sidebar-link">都有测试流程了，为什么还要做CodeReview？</a></li><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#有了codereview就不需要测试了" class="sidebar-link">有了CodeReview就不需要测试了？</a></li><li class="sidebar-sub-header level3"><a href="/jm-team/pages/85a3b2/#只要我在团队推行了codereview流程-代码质量就会迅速提高" class="sidebar-link">只要我在团队推行了CodeReview流程，代码质量就会迅速提高？</a></li></ul></li></ul></li><li><a href="/jm-team/pages/64dca1/" class="sidebar-link">Nuxt爬坑指南</a></li><li><a href="/jm-team/pages/ee1a90/" class="sidebar-link">uniapp学习指南</a></li></ul> </aside> <div><main class="page"><div class="theme-vdoing-wrapper "><div class="articleInfo-wrap" data-v-06970110><div class="articleInfo" data-v-06970110><ul class="breadcrumbs" data-v-06970110><li data-v-06970110><a href="/jm-team/" title="首页" class="iconfont icon-home router-link-active" data-v-06970110></a></li> <li data-v-06970110><a href="/jm-team/newspaper/#前端小报" data-v-06970110>前端小报</a></li></ul> <div class="info" data-v-06970110><div title="作者" class="author iconfont icon-touxiang" data-v-06970110><a href="https://github.com/xugaoyi" target="_blank" title="作者" class="beLink" data-v-06970110>聚名前端</a></div> <div title="创建时间" class="date iconfont icon-riqi" data-v-06970110><a href="javascript:;" data-v-06970110>2022-09-26</a></div> <!----></div></div></div> <!----> <div class="content-wrapper"><div class="right-menu-wrapper"><div class="right-menu-margin"><div class="right-menu-title">目录</div> <div class="right-menu-content"></div></div></div> <h1><img src="">关于代码评审那些不得不说的事儿<!----></h1> <!----> <div class="theme-vdoing-content content__default"><h1 id="关于代码评审那些不得不说的事儿"><a href="#关于代码评审那些不得不说的事儿" class="header-anchor">#</a> 关于代码评审那些不得不说的事儿</h1> <h2 id="什么是codereview"><a href="#什么是codereview" class="header-anchor">#</a> 什么是CodeReview</h2> <p>CodeReview 国内也称代码评审或者代码审查，也简称CR，是指在软件开发过程中，工程师对其他人所写代码做审阅（后文统称CodeReview），以达到控制代码质量的目的。通常的流程都是由代码写作者发起，请团队内其他人审阅代码，其他人对代码提出改进建议，再由代码写作者修改重新提交，直至代码通过大家的审阅为止。</p> <h2 id="为什么要做codereview"><a href="#为什么要做codereview" class="header-anchor">#</a> 为什么要做CodeReview？</h2> <p>其实很多人都不是很重视CodeReview，因为CodeReview的效果短期很难看到，也很难量化衡量。就如同运动一样，偶尔过量的运动不仅对身体无益，可能还会起反作用，不过长期的坚持肯定会让你更健康，但能让你健康多少很难量化，不过前一段时间github上爆火的项目《程序猿延寿指南》里给出了可参考的数据，每周3次45分钟挥拍运动可以减少全因死亡率47%，按其公式折算大概增加9年的预期寿命。运动除了增加预期寿命外，也能显著减少很多疾病的发病率。坚持CodeReview如同坚持运动一样，趋势肯定是让整个代码库更为健康长寿。</p> <p>CodeReview从长期来看，有几个明显的好处，接下来就一一讲一下。</p> <h3 id="提升代码质量"><a href="#提升代码质量" class="header-anchor">#</a> 提升代码质量</h3> <p>假如将一个系统比作一个生命体，一行行代码比作一个个细胞，不好的设计宛如癌细胞，会逐渐扩散，终将杀死系统。而CodeReview的过程就像是T细胞吞噬掉癌细胞，保证系统的健康成长。让系统有更长久的生命力。</p> <div class="custom-block tip"><p class="custom-block-title">提示</p> <p>没有人Review的代码，其代码水准就是写代码人的水准，而被一个团队Review过的代码，它的水准将接近甚至超过整个团队的最高水准。</p></div> <p>因为单个人可能在某些方便做的比较好，集大家之所长就能在各个方面都做的比较好。另外，随着CodeReview流程日常化，每个参与人的编码能力也会逐步提升，无限趋近于团队最高水准，因为在CodeReview的过程中，你可以看到别人做的好的地方，可以学习到经验，也可以看到别人做的不好的地方，吸取到教训。随着时间的流逝，逐渐积累为参与者的能力。</p> <h3 id="提前发现问题"><a href="#提前发现问题" class="header-anchor">#</a> 提前发现问题</h3> <p>在没有CodeReview流程的时候，我们都是依赖于测试，甚至是依赖于功能上线后用户暴露问题，这种发现方式已经偏晚了，尤其是让用户暴露问题的时候可能问题已经非常大了。问题暴露的越晚，风险也就越大。而CodeReview一般是放在代码测试之前，如果能在这个阶段就发现问题就能提前将各种风险扼杀在摇篮中。但是，CodeReview真的能提前发现问题吗？如果能的话，可以提前发现什么样的问题？</p> <p>我个人觉得CodeReview可以提前发现流程或者实现上的问题，尤其是在做业务需求的时候，不同工作经验的人对同一个需求的理解肯定会有差异，代码实现上也会有很大的差异，有时候一点点的理解偏差，导致出现那种失之毫厘谬以千里的后果，写代码的人也会因为处在自己的思维定式中发现不了问题，而别人可能因为经验丰富或者需求相关背景了解更多，就能很轻易发现问题。像这种情况一般出现在团队新人身上，他们对已有系统和业务了解不多，实现需求时很容易出现问题，这时候如果有人帮忙指出就能避免更严重的后果，另外也有助于新人了解业务和融入团队。</p> <p>在CodeReview过程中另外一种问题也比较容易发现，就是那些别人之前踩过的坑。比如Java中SimpleDateFormat其实有线程安全的问题，不了解的人很容易就踩坑了。如果别人踩过这个坑，就可以在CodeReview过程中提前帮你指出来。很多开源的类库，甚至Jdk中很多包或多或少都有使用上的坑…… 这种例子就数不胜数了。</p> <p>当然CodeReview也不是万能的，也有很多问题发现不了的，比如一些边缘Case或者是代码计算结果的准确性，比如你代码实现了一个很复杂公式的计算，你总不能指望有人能通过看代码来发现问题吧。这些还是老老实实去做测试吧！</p> <h3 id="经验和知识的传递"><a href="#经验和知识的传递" class="header-anchor">#</a> 经验和知识的传递</h3> <p>程序猿可以写出能运行的代码，但真正的工程师才能写出低bug、易扩展、易维护的高质量代码，更高级的工程师还能帮其他人成为一名合格的工程师。CodeReview的流程也是高级工程师来帮助其他人最直接的方式。</p> <p>在CodeReview中，你可以看到其他人写出来的优秀代码、优秀的设计，甚至和改动相关的业务背景知识……，Review越多，学到的也越多。另外，即便是哪些不太好的代码，经过别人的Review，必然会留下很多评论或者是改动建议，甚至是别人之前踩的坑，你都能看到，从这些内容上你也可以学到很多新的知识。CodeReview不仅仅是一个提升代码质量方式，它也可以肩负起知识积累和消息集散的功能。</p> <p>举个我之前遇到过的例子，我们之前有个功能需要操作机器上的文件，当然用Java的File也能实现，但是对操作多层级的文件夹时就很不方便了，需要自己写很多的代码，搞不好还容易出bug。后来我发现apache-common包中提供了IOUtils类，可以很方便操作文件夹。我把这个写到CodeReview的评论中，只要看到过的人都会知道原来有这个东西可以用。</p> <p>所以，Review别人代码时请毫不吝啬地留下你的建议吧，另外，CodeReview时也不要忘记关注下别人的建议，说不定可以学到新的东西。</p> <h2 id="如何做好codereview"><a href="#如何做好codereview" class="header-anchor">#</a> 如何做好CodeReview</h2> <p>说完了CodeReview的好处，相信你肯定已经跃跃欲试了，如何能做好CodeReview？这里我根据我的知识和经验分享下我的看法。</p> <h3 id="codereview的步骤"><a href="#codereview的步骤" class="header-anchor">#</a> CodeReview的步骤</h3> <h4 id="了解改动的背景"><a href="#了解改动的背景" class="header-anchor">#</a> 了解改动的背景</h4> <p>CodeReview不是一上来就看代码，这样有可能你会看的云里雾里，纯粹是浪费时间。CodeReview虽然是Review代码，但是首先你的知道你要看的代码实现了什么样的功能，是在什么样的背景下去做的，清楚前因后果之后，你才能知道这个代码大概应该怎么去写，你才能更好的去Review别人的代码、去发现别人的问题。</p> <h4 id="纵观全局"><a href="#纵观全局" class="header-anchor">#</a> 纵观全局</h4> <p>知道背景之后，在你脑海中就会有一个大概的编码思路，也有个流程主线。这个时候可能有两种情况，你和写代码人的思路相同，那你就顺着你们共同的思路去帮忙Review整个流程是否正确。另一种情况就是你们思路不同，你就得看代码去了解写作者的思路，然后确认是谁的思路有问题，或者是谁的思路更好，然后同写作者一起将这个流程优化到更优。</p> <h4 id="逐层细化"><a href="#逐层细化" class="header-anchor">#</a> 逐层细化</h4> <p>确定完整的流程之后，就可以逐步深入到代码细节中了，细节可以Review的地方就很多了，可以看下下一节的内容，这里就先不展开了。</p> <h3 id="codereview的关注点"><a href="#codereview的关注点" class="header-anchor">#</a> CodeReview的关注点</h3> <p>在CodeReview的过程中，如果有一些立足点的话可以帮助大家更好的完成CodeReview的过程，我大概总结出以下几点：</p> <ul><li>功能性：代码所实现的功能是否和预期一样，是否实现了所有必须的功能？</li> <li>复杂性：功能实现是否过于复杂？过于复杂的代码更容易出问题，而且可维护性也会更低。</li> <li>代码风格：代码是否符合团队编码规范？</li> <li>文档&amp;注释：如果代码功能有改动，关注下相关文档和注释有没有同步改动。错误的注释和文档可能会让未来的开发者产生理解成本。</li> <li>代码亮点：如果你看到变更中做得好的地方，也别吝啬你的赞美。</li></ul> <p>上面描述更偏概括性，我们来举一些更详细的例子，帮助大家理解上面几点。</p> <ul><li>代码设计良好，可读性和可维护性高。</li> <li>是否有线程安全的bug。</li> <li>代码没有增加不必要的复杂性。</li> <li>开发者没有写一些目前没有在用的代码，这种无用的代码未来大概率也不会用，所以不要假设。</li> <li>代码有适当的单元测试。</li> <li>测试逻辑设计良好。</li> <li>开发者使用了清晰明了的变量和函数命名。</li> <li>注释清晰明了且实用，并且解释清楚了为什么这么做，而不仅仅是做了啥。</li> <li>代码有相应完善的文档。</li> <li>代码风格符合规范。</li> <li>代码有没有更优的实现？（性能、资源占用……）</li> <li>…… 更多更细节的内容，可以参考谷歌工程实践——代码评审</li></ul> <h3 id="注意事项"><a href="#注意事项" class="header-anchor">#</a> 注意事项</h3> <h4 id="codereview的礼节"><a href="#codereview的礼节" class="header-anchor">#</a> CodeReview的礼节</h4> <p>首先CodeReview不是你个人炫技的舞台，看到别人代码的问题需要礼貌指出，切忌diss别人。其次，CodeReview不要为了提问题而提问题，有些代码就是没问题，你也没必要纠结必须要提个问题，直接通过即可。这里在额外说一点，大部分Review别人的代码，只关注到别人做的不好的地方，而忽视了别人做的好的地方，遇到好的代码、好的设计也别忘记点个赞。</p> <h4 id="codereview应当及时"><a href="#codereview应当及时" class="header-anchor">#</a> CodeReview应当及时</h4> <p>别人提的CodeReview应当及时处理，在很多公司中CodeReview是开发流程中必要的一环，没有Review通过的肯定是不能上线的，如果CodeReview长时间不处理可能会延误后续的流程。另外一点，CodeReview是相互的，今天你及时帮别人Review了，明天别人也会及时帮你Review，与人方便即与己方便。</p> <h2 id="如何写出对codereview友好的代码"><a href="#如何写出对codereview友好的代码" class="header-anchor">#</a> 如何写出对CodeReview友好的代码</h2> <blockquote><p>程序写出来是给人看的，附带能在机器上运行。——Harold Abelson</p></blockquote> <h3 id="提交前先做好自审"><a href="#提交前先做好自审" class="header-anchor">#</a> 提交前先做好自审</h3> <p>提前自己处理掉一些低级错误，可以先借助一些工具完成一些简单的检查。例如我们团队会借助checkstyle、spotbug、sonar、pmd等工具完成代码风格和一些潜在bug的检查。然后自己做好功能的自测，尽可能先消灭一部分bug，为CodeReview减少一些负担。</p> <h3 id="写清楚变更描述"><a href="#写清楚变更描述" class="header-anchor">#</a> 写清楚变更描述</h3> <p>这里对应上文中CodeReview步骤中的了解改动背景，作为代码的写作者，你不能一上来就让别人从代码入手吧，可能看你代码的很多其他人都缺少代码改动相关的上下文信息，完全理解代码成本很高，所以需要在变更描述中将这些信息描述清楚，包括但不仅限于改动背景、改动点、流程、具体设计…… 一句话概括就是<strong>好的变更描述应该说清楚这次是做了什么变更，以及为什么要这么做。</strong></p> <p>更详实的变更描述可以让Review代码人减少理解成本，更快完成CodeReview的流程，你代码改动也就能更快进入后续流程了。</p> <h3 id="单个变更尽可能短"><a href="#单个变更尽可能短" class="header-anchor">#</a> 单个变更尽可能短</h3> <p>一个非常大的变更几乎没有Review，因为大的改动首先就很难Review，其实也更耗费时间，还有出问题的概率也更大，谁Review通过了代码但之后上线出问题，可能是要和你一起背锅的。所以建议大家将大的代码变更尽可能拆小，因为小的变更有以下这些好处:</p> <ul><li><strong>代码评审更快</strong>——与比起花30分钟评审一个大的变更相比，对Review代码的人来说花5分钟审查一系列小的变更更加容易.</li> <li><strong>Review更加彻底</strong>——进行较大的更改后，审阅者和作者往往会因大量详细评论的来回移动而感到沮丧，有时这些评论会漏掉或遗漏重要的观点。</li> <li><strong>减少导致bug的可能性</strong>——由于您所做的更改较少，因此您和您的审阅者更容易有效地推断出CL的影响，并查看是否导致bug。</li> <li><strong>减少不必要的工作</strong>——当你写了一个巨大的变更，然后评审者觉得你总体方向错了，这会导致你浪费大量的工作。</li> <li><strong>更方便合并代码</strong>——因为大型的变更会导致大量的冲突，因此合代码的时候会耗费很多时间，而且可能因合并代码导致问题，我们就出现过好几次代码合并的时候冲掉别人代码的情况。</li> <li><strong>有助于你作出更好的设计</strong>——优雅的设计并且完善一个小的改动比大的改动更加容易</li> <li><strong>降低评审者的难度</strong>——提审部分改动，不会影响你继续编码。</li> <li><strong>如果真出问题，回滚更容易</strong>——这个就不用多解释了吧。</li></ul> <p>对于那些很难拆分的变更，也不是需要完全禁止，有时候就是有改动非常大，而且无法再去拆分了，这时候还是建议通过其他方式来保证代码质量，比如全流程测试。然后也建议做好出问题时的快速恢复方案。</p> <h3 id="注意事项-2"><a href="#注意事项-2" class="header-anchor">#</a> 注意事项</h3> <h4 id="注意自己的情绪"><a href="#注意自己的情绪" class="header-anchor">#</a> 注意自己的情绪</h4> <p>代码的写作者在CodeReview的流程中是弱势的一方，很多人代码在收到评论被要求要修改代码的时候，都有一种不太愿意接受的心态，其实我自己也经常会有这种心态，尤其是在时间比较紧张的情况下。其实这是很正常的心态，但是还是需要去控制自己的情绪的，从评论者的角度出发，他肯定也不是在刁难你，也是希望代码质量能更高。如果真遇到这种情况，首先可以和评论者讨论清楚他的要求是否合理，如果确定了合理性当然还是要改的。但如果在时间比较紧张的情况下，协商是否可以不修改或者是之后再修改，确实有些锦上添花的修改没必要阻塞之后的流程。</p> <h4 id="codereview流程应该尽早提交"><a href="#codereview流程应该尽早提交" class="header-anchor">#</a> CodeReview流程应该尽早提交</h4> <p>日常情况下，还是建议早点提交CodeReview，并留出一定的时间来做修改，尽可能不要让这个流程变的匆忙。大部分公司的实践都是在进入测试流程的时候同时进入CodeReview流程。</p> <h2 id="关于codereview的几个误区"><a href="#关于codereview的几个误区" class="header-anchor">#</a> 关于CodeReview的几个误区</h2> <h3 id="codereview是纯浪费时间"><a href="#codereview是纯浪费时间" class="header-anchor">#</a> CodeReview是纯浪费时间？</h3> <p>如果你的团队刚开始推行CodeReview流程，这个问题肯定是会被很多人问到的。所以是不是呢? 这里我拿锻炼身体类比下，大家都知道坚持运动对健康有益，但如果只是一时兴起，偶尔过量的运动不仅对身体无益，可能还会起反作用。实际上，坚持运动对健康的影响其实很难量化，但我们现在都知道，运动是好的。同样，CodeReview如同运动一样，它可能会耗费一定的精力和时间，但长期坚持下来必然会让整个代码库、整个系统甚至这个团队更加健康。</p> <p>另外，如果一个团队CodeReview机制很成熟，写代码的人随着被Review的次数增加，其代码质量必然也会逐步提交，那么代码中的问题肯定也会逐步减少，随之而来的就是CodeReview的过程越来越轻松。</p> <blockquote><p>困难的路会越走越简单，而简单的路会越走越困难。</p></blockquote> <h3 id="工期很紧-没时间做codereview"><a href="#工期很紧-没时间做codereview" class="header-anchor">#</a> 工期很紧，没时间做CodeReview！</h3> <p>这也是很多团队不做CodeReview的借口。你不做CodeReview省下的时间，会在后面测试，甚至是在后面长期维护中花费更多的时间。我们有句耳熟能详的老话叫做“磨刀不误砍柴工”，其实CodeReview和测试在软件开发过程中就是“磨刀”的工作。</p> <p>做好事前控制而不是事后弥补。因为时候弥补的代价会非常高。</p> <h3 id="只有高级工程师才有资格review别人代码"><a href="#只有高级工程师才有资格review别人代码" class="header-anchor">#</a> 只有高级工程师才有资格Review别人代码？</h3> <p>虽然事实上几乎都是高级工程师在Review别人的代码，我理解造成这种现象的原因其实也比较简单，高级工程师确实经验丰富一些，也更容易Review出别人代码中的问题，所以会留下更多的Review记录，造成只有高级工程师才参与CodeReview的假象。但这绝不意味着初级工程师没有资格Review别人的代码，所谓三人行必有我师，即便是初级工程师也有可能发现Review出别人代码中的问题。</p> <p>即便你暂时确实经验不够丰富，很难找出别人的问题，但你也可以从别人Review代码的过程中学到很多东西，就像上文所说CodeReview也是团队经验和知识的一种传递方式。参与CodeReview也是成为高级工程师必不可少的一步。</p> <h3 id="都有测试流程了-为什么还要做codereview"><a href="#都有测试流程了-为什么还要做codereview" class="header-anchor">#</a> 都有测试流程了，为什么还要做CodeReview？</h3> <p>这个问题算是已经在上文中回答过了，CodeReview需要看很多个方面的内容，而测试只能保证其结果的准确性。</p> <h3 id="有了codereview就不需要测试了"><a href="#有了codereview就不需要测试了" class="header-anchor">#</a> 有了CodeReview就不需要测试了？</h3> <p>问这个问题的人相比于问上个问题的人又走了另一个极端，又把CodeReview和测试放在了对立面上。虽然CodeReview如果做的比较好的话，确实能提前发现一些比较明显的问题，但是做CodeReview的是人，人是无法大规模且精准的去校验程序的执行过程，而这恰恰是自动化测试所擅长的，所以说CodeReview和测试并不是对立关系，而是一种互补关系。</p> <h3 id="只要我在团队推行了codereview流程-代码质量就会迅速提高"><a href="#只要我在团队推行了codereview流程-代码质量就会迅速提高" class="header-anchor">#</a> 只要我在团队推行了CodeReview流程，代码质量就会迅速提高？</h3> <p>首先可以肯定的是代码质量是会提高的，但也许没有那么快。我之前从一个没有CodeReview流程的团队加入到一个有严格CodeReview流程的团队时，有较长一段适应期。我当时最大的感受就是CodeReview太耗时间了，尤其是我刚开始还没适应新团队开发规范的时候，写代码和被Review后改代码所花费的时间基本上五五开，当然之后会好很多。另外，每个人也需要花20%左右的时间和精力去Review别人的代码，相当于花接近三分之一的开发时间来处理CodeReview相关工作，这个比例高到可能你们老板都会怀疑，但我们当时就做到了，结果就是我们的代码质量非常高。</p> <p>以我的经历来看，如果CodeReview想要有效果，时间投入肯定是少不了的，冰冻三尺非一日之寒,滴水石穿非一日之功。不要高估它的短期价值，也不要低估它的长期价值。</p> <blockquote><p>文章来源于公众号，作者：深圳湾码农</p></blockquote></div></div> <!----> <div class="page-edit"><!----> <div class="tags"><a href="/jm-team/tags/?tag=%E5%9B%A2%E9%98%9F%E7%AE%A1%E7%90%86" title="标签">#团队管理</a></div> <div class="last-updated"><span class="prefix">上次更新:</span> <span class="time">2022/11/09, 01:52:48</span></div></div> <div class="page-nav-wapper"><div class="page-nav-centre-wrap"><!----> <a href="/jm-team/pages/64dca1/" class="page-nav-centre page-nav-centre-next"><div class="tooltip">Nuxt爬坑指南</div></a></div> <div class="page-nav"><p class="inner"><!----> <span class="next"><a href="/jm-team/pages/64dca1/">Nuxt爬坑指南</a>→
      </span></p></div></div></div> <div class="article-list"><div class="article-title"><a href="/jm-team/archives/" class="iconfont icon-bi">最近更新</a></div> <div class="article-wrapper"><dl><dd>01</dd> <dt><a href="/jm-team/pages/ee1a90/"><div>
            uniapp学习指南
            <!----></div></a> <span class="date">11-09</span></dt></dl><dl><dd>02</dd> <dt><a href="/jm-team/pages/a46909/"><div>
            JS常用工具函数封装
            <!----></div></a> <span class="date">09-30</span></dt></dl><dl><dd>03</dd> <dt><a href="/jm-team/pages/64dca1/"><div>
            Nuxt爬坑指南
            <!----></div></a> <span class="date">09-30</span></dt></dl> <dl><dd></dd> <dt><a href="/jm-team/archives/" class="more">更多文章&gt;</a></dt></dl></div></div></main></div> <div class="footer"><!----> 
  Theme by
  <a href="https://github.com/xugaoyi/vuepress-theme-vdoing" target="_blank" title="本站主题">Vdoing</a> 
    | Copyright © 2022-2022
    <span>聚名前端 | <a href="https://github.com/xugaoyi/vuepress-theme-vdoing/blob/master/LICENSE" target="_blank">MIT License</a></span></div> <div class="buttons"><div title="返回顶部" class="button blur go-to-top iconfont icon-fanhuidingbu" style="display:none;"></div> <div title="去评论" class="button blur go-to-comment iconfont icon-pinglun" style="display:none;"></div></div> <!----> <!----> <!----></div><div class="global-ui"></div></div>
    <script src="/jm-team/assets/js/app.99b82987.js" defer></script><script src="/jm-team/assets/js/5.d18fc731.js" defer></script><script src="/jm-team/assets/js/6.c8a66f32.js" defer></script><script src="/jm-team/assets/js/15.811e7806.js" defer></script>
  </body>
</html>
